//
//  RxSwiftObservableViewController.swift
//  DemoProject
//
//  Created by hao on 2018/7/26.
//  Copyright © 2018年 hao. All rights reserved.
//

import UIKit
import RxSwift

// RxSwift提供的对系统多线程(GCD、OperationQueue)调度的封装
//        ConcurrentDispatchQueueScheduler
//        OperationQueueScheduler
//        SerialDispatchQueueScheduler

// Subscribe: 订阅
// doOn: 监听事件的生命周期，在每一次事件发送前被调用
// dispose: 取消订阅
// DisposeBag: 管理多个订阅行为的销毁(DisposeBag的对象 dealloc 时，对它持有的所有订阅行为都调用 dispose())  使用 ->
//  let disposeBag = DisposeBag();
//  observable1.subscribe { event in
//      print(event)
//  }.disposed(by: disposeBag)

class RxSwiftObservableViewController: BaseViewController {

    let funcDescption = """
    Observable的方法
    1. just()
     （1）该方法通过传入一个默认值来初始化。
     （2）可以显式声明 observable 的类型为 Observable<Int>，即指定 Observable 所发出的事件携带的数据类型必须是 Int 类型。
      let observable = Observable<Int>.just(5)
    
    2. of()
     （1）该方法可以接受可变数量的参数（必需要是同类型的）
     （2）下面样例没有显式地声明出 Observable 的泛型类型，Swift 也会自动推断类型。
      let observable = Observable.of("A", "B", "C")
    
    3. from()
     （1）该方法需要一个数组参数。
     （2）下面样例中数据里的元素就会被当做这个 Observable 所发出 event 携带的数据内容，最终效果同上面 of() 样例是一样的。
      let observable = Observable.from(["A", "B", "C"])
    
    4. empty()
      该方法创建一个空内容的 Observable 序列。
      let observable = Observable<Int>.empty()
    
    5. never()
      该方法创建一个永远不会发出 Event（也不会终止）的 Observable 序列。
      let observable = Observable<Int>.never()
    
    6. error()
      该方法创建一个不做任何操作，而是直接发送一个错误的 Observable 序列。
      enum MyError: Error {
          case A
          case B
      }
      let observable = Observable<Int>.error(MyError.A)
    
    7. range()
     （1）该方法通过指定起始和结束数值，创建一个以这个范围内所有值作为初始值的 Observable 序列。
     （2）下面样例中，两种方法创建的 Observable 序列都是一样的。
      let observable = Observable.range(start: 1, count: 5)
      let observable = Observable.of(1, 2, 3 ,4 ,5)
    
    8. repeatElement()
     （1）该方法创建一个可以无限发出给定元素的 Event 的 Observable 序列（永不终止）。
      let observable = Observable.repeatElement(1)
    
    9. generate()
     （1）该方法创建一个只有当提供的所有的判断条件都为 true 的时候，才会给出动作的 Observable 序列。
     （2）下面样例中，两种方法创建的 Observable 序列都是一样的。
        // 使用generate()方法
        let observable = Observable.generate(
            initialState: 0,
            condition: { $0 <= 10 },
            iterate: { $0 + 2 }
        )
    
        //使用of()方法
        let observable = Observable.of(0 , 2 ,4 ,6 ,8 ,10)
    
    10. create()
        (1) 该方法接受一个 block 形式的参数，任务是对每一个过来的订阅进行处理。
        (2) 以下增加了订阅相关的代码
        // 这个block有一个回调参数observer就是订阅这个Observable对象的订阅者
        // 当一个订阅者订阅这个Observable对象的时候，就会将订阅者作为参数传入这个block来执行一些内容
        let observable = Observable<String>.create { observer in
            // 对订阅者发出了.next事件，且携带了一个数据"hao.com"
            observer.onNext("hao.com")
            // 对订阅者发出了.completed事件
            observer.onCompleted()
            // 因为一个订阅行为会有一个Disposable类型的返回值，所以在结尾一定要returen一个Disposable
            return Disposables.create()
        }
        
        //订阅测试
        observable.subscribe {
            print($0)  // next(hao.chen.com)
        }
    
    11. deferred()
        该个方法相当于是创建一个 Observable 工厂，通过传入一个 block 来执行延迟 Observable 序列创建的行为，而这个 block 里就是真正的实例化序列对象的地方。
        //用于标记是奇数、还是偶数
        var isOdd = true
        //使用deferred()方法延迟Observable序列的初始化，通过传入的block来实现Observable序列的初始化并且返回。
        let factory : Observable<Int> = Observable.deferred {
        
            //让每次执行这个block时候都会让奇、偶数进行交替
            isOdd = !isOdd
        
            //根据isOdd参数，决定创建并返回的是奇数Observable、还是偶数Observable
            if isOdd {
                return Observable.of(1, 3, 5 ,7)
            } else {
                return Observable.of(2, 4, 6, 8)
            }
        }
        
        //第1次订阅测试
        factory.subscribe { event in
            print("\\(isOdd, event)")
        }
        
        //第2次订阅测试
        factory.subscribe { event in
            print("\\(isOdd, event)")
        }
    
    12. interval()
       （1）这个方法创建的 Observable 序列每隔一段设定的时间，会发出一个索引数的元素。而且它会一直发送下去。
       （2）下面方法让其每 1 秒发送一次，并且是在主线程（MainScheduler）发送。
        let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
        observable.subscribe { event in
            print(event)
        }
    
    13. timer()
        (1）这个方法有两种用法，一种是创建的 Observable 序列在经过设定的一段时间后，产生唯一的一个元素。
        // 5秒种后发出唯一的一个元素0
        let observable = Observable<Int>.timer(5, scheduler: MainScheduler.instance)
        observable.subscribe { event in
            print(event)
        }
        
        (2) 另一种是创建的 Observable 序列在经过设定的一段时间后，每隔一段时间产生一个元素。
        //延时5秒种后，每隔1秒钟发出一个元素
        let observable = Observable<Int>.timer(5, period: 1, scheduler: MainScheduler.instance)
        observable.subscribe { event in
            print(event)
        }
    """
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setupView()
        self.testObservableCreate()
        self.testObservableDeferred()
//        self.testObservableInterval()
//        self.testObservableTimer()
//        self.testObservableSubscribe()
        self.testObservableDoOn()
    }
    
    private func setupView() {
        let y = kStatusBarAndNaviHeight()
        let height = MainScreenHeight()-y
        let textView = UITextView(frame: CGRect(x: 0, y: y, width: MainScreenWidth(), height: height))
        self.view.addSubview(textView)
        textView.font = UIFont.systemFont(ofSize: UIFont.systemFontSize)
        textView.text = funcDescption
    }
    
}

// MARK: 创建 Observable
extension RxSwiftObservableViewController {
    
    fileprivate func testObservableCreate() {
        let observable = Observable<String>.create { (observer) -> Disposable in
            // 对订阅者发出了.next事件，且携带了一个数据"hao.chen.com"
            observer.onNext("hao.chen.com")
            // 对订阅者发出了.completed事件
            observer.onCompleted()
            // 因为一个订阅行为会有一个Disposable类型的返回值，所以在结尾一定要returen一个Disposable
            return Disposables.create()
        }
        // 订阅测试
        _ = observable.subscribe {
            print(info: $0) // next(hao.chen.com)
        }
        //        _ = observable.subscribe({ (event) in
        //            event.element
        //        })
    }
    
    // 延迟
    fileprivate func testObservableDeferred() {
        //用于标记是奇数、还是偶数
        var isOdd = true
        //使用deferred()方法延迟Observable序列的初始化，通过传入的block来实现Observable序列的初始化并且返回。
        let factory = Observable<Int>.deferred { () -> Observable<Int> in
            isOdd = !isOdd
            if isOdd {
                return Observable.of(1, 3, 5, 7)
            } else {
                return Observable.of(2, 4, 6, 8)
            }
        }
        // 第一次订阅 (闭包会调用Observable.of()创建时参数个数的次数)
        _ = factory.subscribe { (event) in
            print(info: "\((isOdd, event))")
        }
        // 第二次订阅
        _ = factory.subscribe { (event) in
            print(info: "\((isOdd, event))")
        }
    }
    
    // Observable 序列每隔一段设定的时间，会发出一个索引数的元素。而且它会一直发送下去
    fileprivate func testObservableInterval() {
        _ = Observable<Int>.interval(1, scheduler: MainScheduler.instance).subscribe { (event) in
            print(info: event)
        }
    }
    
    fileprivate func testObservableTimer() {
        // 第一种用法: 5秒种后发出唯一的一个元素0
        _ = Observable<Int>.timer(5, scheduler: MainScheduler.instance).subscribe { event in
            print(info: "\((event, " -> \(Thread.current)"))")
        }
        
        // 第二种用法: 设定每隔一段时间产生一个元素
        _ = Observable<Int>.timer(5, period: 3, scheduler: MainScheduler.instance).subscribe({ (event) in
            print(info: event)
        })
    }
    
}

// MARK: 销毁订阅者
extension RxSwiftObservableViewController {
    
    fileprivate func subscribeDestroy() {
        let subscribe = Observable<String>.of("H", "A", "O").subscribe { (event) in
            print(info: event)
        }
        // 2秒后释放
        DispatchQueue.main.asyncAfter(deadline: DispatchTime(uptimeNanoseconds: 2)) {
            subscribe.dispose()
        }
        
        // 只需要再次初始化 DisposeBag() 就能释放其对象所持有的订阅者
        let disposeBag = DisposeBag()
        Observable<String>.of("H", "A", "O").subscribe { (event) in
            print(info: event)
        }.disposed(by: disposeBag) // 将订阅者添加到 DisposeBag() 对象管理
    }
    
}

// MARK: 订阅 Observable
extension RxSwiftObservableViewController {
    
    fileprivate func testObservableSubscribe() {
        // subscribe() 方法的 onNext、onError、onCompleted 和 onDisposed 这四个回调 block 参数都是有默认值的
        _ = Observable<String>.of("H", "A", "O").subscribe(onNext: { (event) in
            print(info: event)
        }, onError: { (error) in
            print(info: error)
        }, onCompleted: {
            print(info: "onCompleted")
        }, onDisposed: {
            print(info: "onDisposed")
        })
    }
    
}

// MARK: doOn事件监听
extension RxSwiftObservableViewController {
    
    fileprivate func testObservableDoOn() {
        _ = Observable<String>.of("H", "A", "O")
            // 每一个block会在订阅对应的回调block之前调用 (do()的参数onDisposed 会在subscribe()的参数onDisposed之后调用)
            .do(onNext: { (event) in
                print(info: "do -> \(event)")
            }, onError: { (error) in
                print(info: "do -> \(error)")
            }, onCompleted: {
                print(info: "do -> onCompleted")
            }, onSubscribe: {
                print(info: "do -> onSubscribe")
            }, onSubscribed: {
                print(info: "do -> onSubscribed")
            }, onDispose: {
                print(info: "do -> onDispose")
            })
            .subscribe(onNext: { (event) in
                print(info: "subscribe -> \(event)")
            }, onError: { (error) in
                print(info: "subscribe -> \(error)")
            }, onCompleted: {
                print(info: "subscribe -> onCompleted")
            }, onDisposed: {
                print(info: "subscribe -> onDisposed")
            })
    }
    
}



